import { NULL } from "@/utils/UtilCommon";

// @ts-ignore
export default {
  /**
   * 反向获取元素
   */
  rGet<T>(array: T[], index: number): T {
    return array[array.length - index - 1];
  },
  /**
   * 获取元素
   * @param array 数组
   * @param index 索引，支持负数
   */
  get<T>(array: T[] | NULL, index: number): T | null {
    if (array == null) {
      return null;
    }
    index = index > 0 ? index : array.length + index;
    return array[index];
  },
  /**
   * 数组是否为空
   * @param array
   * @return true则空
   */
  isEmpty<T>(array: T[] | null | undefined): boolean {
    return array == null || array.length === 0;
  },
  /**
   * 是否非空
   * @param array
   * @return true则非空
   */
  isNotEmpty<T>(array: T[] | null | undefined): boolean {
    return !this.isEmpty(array);
  },
  /**
   * 是否包含
   * @param array
   * @param val
   */
  contains<T>(array: T[], val: T) {
    return array.findIndex((value) => value === val) !== -1;
  },
  /**
   * 是否包含
   * @param array
   * @param predicate
   */
  // @ts-ignore
  contains2<T>(array: T[] | null | undefined, predicate: (T) => boolean) {
    if (array == null) {
      return false;
    }
    for (const item of array) {
      if (predicate(item)) {
        return true;
      }
    }
    return false;
  },
  /**
   * 映射数组
   * @param array 数组
   * @param mapper 映射函数
   * @return 映射后的数组
   */
  map<T, R>(
    array: T[] | null | undefined,
    mapper: (item: T, index: number) => R | null
  ): R[] {
    if (this.isEmpty(array)) {
      return [];
    }
    const result: R[] = [];
    for (let i = 0; i < array!.length; i++) {
      const value = mapper(array![i], i);
      if (value != null) {
        result.push(value);
      }
    }
    return result;
  },
  /**
   * 映射map为数组
   * @param map
   * @param mapper
   * @param ignoreNull 是否忽略null值
   */
  mapToList<T>(
    map: object | null | undefined,
    mapper: (key: string, value: any) => T | null,
    ignoreNull = true
  ): Array<T | null> {
    if (map == null) {
      return [];
    }
    const result: Array<T | null> = [];
    for (const key in map) {
      // @ts-ignore
      const value = mapper(key, map[key]);
      if (ignoreNull && value == null) {
        continue;
      }
      result.push(value);
    }
    return result;
  },
  /**
   * 集合转化为map
   * @param coll 集合
   * @param keyMapper key映射
   * @param valueMapper value映射
   */
  toMap<T, V>(
    coll: T[] | null | undefined,
    // @ts-ignore
    keyMapper: (T, index) => string,
    // @ts-ignore
    valueMapper: (T, index) => V
  ): any {
    if (coll == null) {
      return;
    }
    const result = {};
    coll.forEach(
      (item, index) =>
        // @ts-ignore
        (result[keyMapper(item, index)] = valueMapper(item, index))
    );
    return result;
  },
  /**
   * 批量获取集合元素
   * @param coll 集合
   * @param consumer 消费者
   * @param batchSize 每次处理数量
   */
  batchGet<T>(
    coll: T[] | null | undefined,
    consumer: (batch: T[]) => void,
    batchSize = 50
  ) {
    if (this.isEmpty(coll)) {
      return;
    }
    batchSize = batchSize <= 0 ? 1 : batchSize;
    let batch: T[] = [];
    for (const element of coll!) {
      batch.push(element);
      if (batch.length == batchSize) {
        consumer(batch);
        batch = [];
      }
    }
    if (batch.length != 0) {
      consumer(batch);
    }
  },
  /**
   * 过滤列表
   * @param coll 列表
   * @param test 测试函数
   * @return 过滤后的列表
   */
  filter<T>(coll: T[] | null | undefined, test: (item: T) => boolean): T[] {
    if (this.isEmpty(coll)) {
      return [];
    }
    const result: T[] = [];
    for (const item of coll!) {
      if (test(item)) {
        result.push(item);
      }
    }
    return result;
  },
  /**
   * 分页
   * @param coll 集合
   * @param pageNum 页码，从1开始
   * @param pageSize 页大小
   * @return 指定页的集合
   */
  page<T>(
    coll: T[] | null | undefined,
    pageNum: number,
    pageSize: number
  ): T[] {
    if (coll == null) {
      return [];
    }
    return coll.slice((pageNum - 1) * pageSize, pageNum * pageSize);
  },
  /**
   * 创建数组，通过重复元素
   * @param element
   * @param size
   */
  ofRepeated<T>(element: T, size: number): T[] {
    const result: T[] = [];
    for (let i = 0; i < size; i++) {
      result.push(element);
    }
    return result;
  },
  /**
   * 排序
   * @param list 集合
   * @param compareFn 比较函数
   */
  sort<T>(list: T[] | null | undefined, compareFn?: (a: T, b: T) => number) {
    if (list == null) {
      return list;
    }
    return list.sort(compareFn);
  },
  /**
   * 排序
   * @param list 集合
   * @param mapper 将元素映射到数字
   */
  sortByMapper<T>(
    list: T[] | null | undefined,
    // @ts-ignore
    mapper: (T) => number | null | undefined
  ) {
    if (list == null) {
      return list;
    }

    return list.sort((a, b) => {
      let ra = mapper(a);
      ra = ra != null ? ra : Number.MAX_VALUE;

      let rb = mapper(b);
      rb = rb != null ? rb : Number.MAX_VALUE;

      return ra - rb;
    });
  },
};
